﻿
using NAudio.Wave;
using NAudio.MediaFoundation;
using System;
using System.IO;
using System.Collections.Generic;
using FFMpegCore;

namespace SpeechRecognitionCSharp
{
    /// <summary>
    /// 音频读取器
    /// 使用NAudio库读取多种格式的音频文件
    /// </summary>
    internal class AudioReader : IAudioReader
    {
        private int sampleRate;
        private float[] samples;

        /// <summary>
        /// 默认构造函数
        /// </summary>
        private AudioReader()
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="fileName">音频文件路径</param>
        public AudioReader(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                throw new ArgumentNullException(nameof(fileName));

            if (!File.Exists(fileName))
                throw new FileNotFoundException("音频文件不存在", fileName);

            ReadAudioFile(fileName);
        }

        /// <summary>
        /// 读取音频文件
        /// </summary>
        /// <param name="fileName">音频文件路径</param>
        private void ReadAudioFile(string fileName)
        {
            // 初始化MediaFoundation，用于支持MP3、MP4等格式
            MediaFoundationApi.Startup();

            try
            {
                using (var audioFileReader = new AudioFileReader(fileName))
                {
                    // 获取采样率
                    sampleRate = audioFileReader.WaveFormat.SampleRate;

                    // 读取所有音频样本
                    int samplesCount = (int)(audioFileReader.Length / audioFileReader.WaveFormat.BlockAlign);
                    samples = new float[samplesCount * audioFileReader.WaveFormat.Channels];
                    audioFileReader.Read(samples, 0, samples.Length);

                    // 如果是多声道，转换为单声道
                    if (audioFileReader.WaveFormat.Channels > 1)
                    {
                        float[] monoSamples = new float[samplesCount];
                        for (int i = 0; i < samplesCount; i++)
                        {
                            // 简单平均所有声道
                            float sum = 0;
                            for (int j = 0; j < audioFileReader.WaveFormat.Channels; j++)
                            {
                                sum += samples[i * audioFileReader.WaveFormat.Channels + j];
                            }
                            monoSamples[i] = sum / audioFileReader.WaveFormat.Channels;
                        }
                        samples = monoSamples;
                    }
                }
            }
            finally
            {
                // 关闭MediaFoundation
                MediaFoundationApi.Shutdown();
            }
        }

        /// <summary>
        /// 音频采样率
        /// </summary>
        public int SampleRate
        {
            get => sampleRate;
        }

        /// <summary>
        /// 音频采样数据
        /// </summary>
        /// <remarks>采样数据已归一化到[-1, 1]范围
        /// 如果是多声道音频，已转换为单声道</remarks>
        public float[] Samples
        {
            get => samples;
        
        }

        /// <summary>
        /// 分块读取音频数据
        /// </summary>
        /// <param name="startIndex">起始索引</param>
        /// <param name="length">读取长度</param>
        /// <returns>音频数据块</returns>
        public float[] ReadSamples(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex >= samples.Length)
                throw new ArgumentOutOfRangeException(nameof(startIndex));

            int actualLength = Math.Min(length, samples.Length - startIndex);
            float[] result = new float[actualLength];
            Array.Copy(samples, startIndex, result, 0, actualLength);
            return result;
        }
        
        /// <summary>
        /// 获取音频文件的长度（秒）
        /// </summary>
        /// <param name="filePath">音频文件路径</param>
        /// <returns>音频文件长度（秒）</returns>
        public static double GetAudioDuration(string filePath)
        {
            using (var audioFileReader = new NAudio.Wave.AudioFileReader(filePath))
            {
                return audioFileReader.TotalTime.TotalSeconds;
            }
        }
        
        /// <summary>
        /// 分割音频文件为最长20分钟的块，并将分割后的wav文件压缩为mp3
        /// </summary>
        /// <param name="filePath">原始音频文件路径</param>
        /// <returns>压缩后的mp3文件路径列表</returns>
        public static List<string> SplitAudioFile(string filePath)
        {
            var resultFiles = new List<string>();
            var directory = Path.GetDirectoryName(filePath);
            var fileName = Path.GetFileNameWithoutExtension(filePath);
            
            using (var audioFileReader = new NAudio.Wave.AudioFileReader(filePath))
            {
                // 5分钟的字节数 - 减小分割文件大小
                long bytesPerBlock = (long)(audioFileReader.WaveFormat.AverageBytesPerSecond * 600);
                long position = 0;
                int blockIndex = 0;
                
                // 确保目标目录存在 - 使用当前文件所在目录下的audioTmp文件夹
                string targetDir = Path.Combine(directory ?? ".", "audioTmp");
                Directory.CreateDirectory(targetDir);
                
                while (position < audioFileReader.Length)
                {
                    // 计算当前块的实际大小
                    long blockSize = Math.Min(bytesPerBlock, audioFileReader.Length - position);
                    
                    // 创建临时wav文件路径
                    string wavFilePath = Path.Combine(
                        targetDir, 
                        $"{fileName}_part{blockIndex}.wav");
                    
                    // 创建目标mp3文件路径
                    string mp3FilePath = Path.Combine(
                        targetDir, 
                        $"{fileName}_part{blockIndex++}.mp3");
                    
                    // 读取并保存音频块为wav
                    using (var writer = new NAudio.Wave.WaveFileWriter(wavFilePath, audioFileReader.WaveFormat))
                    {
                        audioFileReader.Position = position;
                        var buffer = new byte[blockSize];
                        int bytesRead = audioFileReader.Read(buffer, 0, buffer.Length);
                        writer.Write(buffer, 0, bytesRead);
                    }
                    
                    // 使用FFMpegCore将wav文件压缩为mp3
                    FFMpegCore.FFMpegArguments
                        .FromFileInput(wavFilePath)
                        .OutputToFile(mp3FilePath, true, options => options
                            .WithAudioBitrate(FFMpegCore.Enums.AudioQuality.Normal) // 128kbps
                            .WithAudioCodec("libmp3lame")
                            .WithAudioSamplingRate(16000) // 采样率16000Hz
                            .WithCustomArgument("-ac 1") // 单声道 (替代WithAudioChannels)
                            .WithCustomArgument("-sample_fmt s16") // 位深度16位
                        )
                        .ProcessSynchronously(); // 使用ProcessSynchronously替代Process(true)
                    
                    // 将mp3文件路径添加到结果列表
                    resultFiles.Add(mp3FilePath);
                    
                    // 可选：删除临时wav文件以节省空间
                     File.Delete(wavFilePath);

                    position += blockSize;
                }
            }
            
            return resultFiles;
        }
    }
}
